package org.snail.attendence.job;

import com.alibaba.druid.util.StringUtils;
import lombok.NonNull;
import lombok.extern.log4j.Log4j;
import org.apache.log4j.Logger;
import org.snail.attendence.bean.AbnormalAttendanceDTO;
import org.snail.attendence.bean.AliWorkDTO;
import org.snail.common.DataUtils;
import org.snail.common.DateUtils;
import org.snail.common.ExcelUtils;
import org.snail.common.StringUtils2;
import org.snail.constant.ErrCodeConstant;
import org.snail.constant.WorkSheetConstant;
import org.snail.employee.bean.EmpCondition;
import org.snail.employee.bean.EmployeesDO;
import org.snail.employee.mapper.AddressMapper;
import org.snail.employee.mapper.EmployeesMapper;
import org.snail.exception.BaseException;
import org.snail.exception.CommonException;
import org.snail.other.bean.GroupDO;
import org.snail.other.mapper.GroupMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


//统计打卡异常的信息
@Log4j
@Service
public class AbnormalRecord { //test
    private static final Logger LOGGER = Logger.getLogger(AbnormalRecord.class);

    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private EmployeesMapper employeesMapper;

    //为提高异常的查询效率，先从缓存中取，然后返回成Map<GroupDO,Map<EmployeesDO, List<AbnormalAttendanceDTO>>>  ,map中取数据会更快一点
    //业务步骤：全局变量注意线程安全
    //1.将返回的异常数据全部转成上述map,方便存储以及快速提取
    private List<AbnormalAttendanceDTO> abnormalList = Collections.synchronizedList(new ArrayList<>());    //每个人对应的异常考勤
    private Map<String, EmployeesDO> onePersonMap = new ConcurrentHashMap<>();      //人对应一个Map
    private static Map<Integer, String> abnormalityOfAttendanceDescribeMap;

    static {
        abnormalityOfAttendanceDescribeMap = new HashMap<>();
        abnormalityOfAttendanceDescribeMap.put(1, "上班忘记打卡");
        abnormalityOfAttendanceDescribeMap.put(2, "下班忘记打卡");
        abnormalityOfAttendanceDescribeMap.put(3, "严重迟到");
        abnormalityOfAttendanceDescribeMap.put(4, "工作时长小于8小时");
        abnormalityOfAttendanceDescribeMap.put(5, "调休+上班时间小于8小时");
        abnormalityOfAttendanceDescribeMap.put(6,"周末加班时长与审批单不符");
        abnormalityOfAttendanceDescribeMap.put(7,"加班加上上班时间小于8小时");
        abnormalityOfAttendanceDescribeMap.put(8,"事假加上上班时间小于8小时");
        abnormalityOfAttendanceDescribeMap.put(9,"外出审批异常");
        abnormalityOfAttendanceDescribeMap.put(12, "上下班均未打卡");
    }

    /**
     * 该类的核心方法: 获取异常考勤信息
     *
     * @param list 全部考勤list
     * @return 异常考勤list
     * @throws BaseException  常见错误
     * @throws ParseException 转换错误
     */
    public List<AbnormalAttendanceDTO> getAbnormalAttendance(List<AliWorkDTO> list) throws BaseException, ParseException {
        abnormalList.clear();
        /**
         * 保存对应员工日期的考勤
         * Map<WB28982,<07-12,AliWorkDTO>>
         */
        Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap = new HashMap<>();
        for(AliWorkDTO aliWorkDTO : list){
            AliWorkDTO aliWorkDTOCopy = new AliWorkDTO();
            BeanUtils.copyProperties(aliWorkDTO,aliWorkDTOCopy);
            String aliNum = aliWorkDTO.getAliNumber();
            String attendenceDate = aliWorkDTO.getDateStr();
            if(attendenceDate!=null){
                attendenceDate = attendenceDate.substring(3,8);
            }
            if(aliNum!=null){
                if(allAttendenceDOMap.get(aliNum)==null){
                    allAttendenceDOMap.put(aliNum,new HashMap<>());
                }
                allAttendenceDOMap.get(aliNum).put(attendenceDate,aliWorkDTOCopy);
            }
        }

        if (list != null && !list.isEmpty()) {
            for (AliWorkDTO aliWorkDTO : list) {
                judgeAttendance(aliWorkDTO,allAttendenceDOMap);  //判断考勤是否异常
            }
        }
        return abnormalList;
    }

    /**
     * 异常考勤信息:1:"上班忘记打卡",2:"下班忘记打卡",3:"严重迟到",4:"工作时长小于9小时",5:"调休+上班时间小于9小时"
     * <p>
     * 判断考勤是否合格
     *
     * @param aliWorkDTO 考勤信息
     */
    private void judgeAttendance(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws BaseException, ParseException {
        if (aliWorkDTO.getEmployeeName().equals("康建杰")) {
            int a = 1;
        }
        if (removeSpecialAttendance(aliWorkDTO)) {        //去掉相关特殊的排版，以及外出事假等
            if (!StringUtils.isEmpty(aliWorkDTO.getOrder())) {
                if (aliWorkDTO.getOrder().equals(WorkSheetConstant.ORDER_FREE_TYPE)) {   //1.周末考勤
                    if (!StringUtils.isEmpty(aliWorkDTO.getApproval())&&aliWorkDTO.getApproval().contains(WorkSheetConstant.APPROVAL_OVERTIME_TYPE)) {     //1.1 如果周末没有考勤数据，跳过
                        orderRest(aliWorkDTO,allAttendenceDOMap);       //1.2 周末加班数据，判断加班是否有上下班打卡时间，并且判断时间是否有效
                    }
                } else {
                    judgeWeekAttendance(aliWorkDTO,allAttendenceDOMap);         //2.工作日考勤
                }
            }
        }

    }


    //处理休息的情况
    private void orderRest(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws BaseException, ParseException {
        int abnormalType = 0;
        abnormalType = weekendOverTime(aliWorkDTO,allAttendenceDOMap);
        if (abnormalType != 0) {
//            EmployeesDO empFromAliwork = getEmpFromAliwork(aliWorkDTO);   //1.根据aliworkDTO 获取人员相关信息
//            if(empFromAliwork!=null){
            createEmpAbnormalList(aliWorkDTO, abnormalType, null);
//            }
        }
    }

    /**
     * 处理周末加班的异常情况
     *
     * @param aliWorkDTO
     * @return
     */
    private int weekendOverTime(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws ParseException {
        int abnormalType = 0;
        //判断加班上下班有没有打卡
        abnormalType = punchWeekendComment(aliWorkDTO);
        if (abnormalType == 0) {
            //上下班都打卡的情况判断审批单时间和实际上班时间是否一致
            //weekendMins:周末上班时长
            Double weekendMins = countWeekendMins(aliWorkDTO,allAttendenceDOMap);
            if (weekendMins == 0.0) {
                abnormalType = WorkSheetConstant.ABNORMAL_TYPE_OVERTIME_APPROVAL;
            }
        }
        return abnormalType;
    }


    /**
     * 判断周末加班得情况是否缺卡
     * 周末加班没有打卡在考勤结果中不会显示缺卡
     *
     * @param aliWorkDTO
     * @return
     */
    private int punchWeekendComment(AliWorkDTO aliWorkDTO) {
        int abnormalType = 0;
        String approval = aliWorkDTO.getApproval();
        if (!StringUtils.isEmpty(approval)) {
            String punch1 = aliWorkDTO.getPunchTime1();
            String comment1 = aliWorkDTO.getPunchComment1();
            String punch2 = aliWorkDTO.getPunchTime2();
            String comment2 = aliWorkDTO.getPunchComment2();
            if (StringUtils.isEmpty(punch1) && StringUtils.isEmpty(comment1) && StringUtils.isEmpty(punch2) && StringUtils.isEmpty(comment2)) {
                abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH_PUNCH2;
            } else if (StringUtils.isEmpty(punch1) && StringUtils.isEmpty(comment1)) {
                abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH;
            } else if (StringUtils.isEmpty(punch2) && StringUtils.isEmpty(comment2)) {
                abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH2;
            }
        }
        return abnormalType;
    }


    //工作日考勤
    private void judgeWeekAttendance(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws BaseException, ParseException {
        int abnormalType = 0;
        String approval = aliWorkDTO.getApproval();
        //计算考勤时间
        Double absentMins = countWorkMins(aliWorkDTO,allAttendenceDOMap);


        /*
         *  下面分两种情况审批单是否为空
         */
        if (!isPunchIn(aliWorkDTO) && !isPunchOut(aliWorkDTO)&&StringUtils.isEmpty(approval)) {
            abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH_PUNCH2;
        } else if (!isPunchIn(aliWorkDTO)&&StringUtils.isEmpty(approval)) {     //上班忘记打卡
            abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH;
        } else if (!isPunchOut(aliWorkDTO)&&StringUtils.isEmpty(approval)) {    //下班忘记打卡
            abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH2;
        } else if (StringUtils.isEmpty(approval)) {
            if (serious_late(aliWorkDTO)) {   //迟到
                abnormalType = WorkSheetConstant.ABNORMAL_TYPE_LATE_ARRIVAL;
            } else if (absentMins > 0) {
                if (isComment(aliWorkDTO)) {                                   //排除 不在考勤组
                    abnormalType = WorkSheetConstant.ABNORMAL_TYPE_BELOW_9;//考勤时间小于9小时
                }
            }
        } else {
            //处理有审批单的情况
            //先排除有审批单,有工作时长小于480分钟的时候一天必须打卡两次。
            //加班必须有两次打卡
            if(!StringUtils.isEmpty(aliWorkDTO.getAttendenceMin())&&
                    Double.parseDouble(aliWorkDTO.getAttendenceMin())<WorkSheetConstant.WORK_HOUR&&
                    !approval.contains(WorkSheetConstant.APPROVAL_WORK_OVERTIME)){
                if(!approval.contains(WorkSheetConstant.APPROVAL_OUT_TYPE)){
                    if(StringUtils.isEmpty(aliWorkDTO.getPunchTime1())&&StringUtils.isEmpty(aliWorkDTO.getPunchTime2())){
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH_PUNCH2;
                    }else if(StringUtils.isEmpty(aliWorkDTO.getPunchTime1())){
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH;
                    }else if(StringUtils.isEmpty(aliWorkDTO.getPunchTime2())){
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH2;
                    }
                }
            }else if(approval.contains(WorkSheetConstant.APPROVAL_WORK_OVERTIME)){
                if(StringUtils.isEmpty(aliWorkDTO.getPunchTime1())&&StringUtils.isEmpty(aliWorkDTO.getPunchTime2())){
                    abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH_PUNCH2;
                }else if(StringUtils.isEmpty(aliWorkDTO.getPunchTime1())){
                    abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH;
                }else if(StringUtils.isEmpty(aliWorkDTO.getPunchTime2())){
                    abnormalType = WorkSheetConstant.ABNORMAL_TYPE_MISS_PUNCH2;
                }
            }
            if(abnormalType==0){
                //有审批单 有工作时长 上下班都打卡了
                //在算是否有异常
                if (absentMins > 0) {
                    //不同类型的审批单异常报不同错误
                    //请假,调休,加班,外出
                    if (approval.contains(WorkSheetConstant.APPROVAL_TO_GO_OUT) && approval.contains(WorkSheetConstant.APPROVAL_WORK_OVERTIME)) {
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_TO_GO_OUT;
                    } else if (approval.contains(WorkSheetConstant.APPROVAL_PRIVATE_AFFAIR_LEAVE)) {
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_AFFAIR_LEAVE;
                    } else if (approval.contains(WorkSheetConstant.APPROVAL_WORK_OVERTIME)) {
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_WORK_OVERTIME;
                    } else if (approval.contains(WorkSheetConstant.APPROVAL_PAID_LEAVE)) {
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_APPROVAL_BELOW_9;
                    } else {
                        log.error("未知的审批单:" + approval);
                    }
                }else{
                    if(approval.contains(WorkSheetConstant.APPROVAL_OUT_TYPE)&&approval.contains(WorkSheetConstant.APPROVAL_OVERTIME_TYPE)){
                        abnormalType = WorkSheetConstant.ABNORMAL_TYPE_TO_GO_OUT;
                    }
                }
            }
        }
        if (abnormalType != 0) {
//            EmployeesDO empFromAliwork = getEmpFromAliwork(aliWorkDTO);   //1.根据aliworkDTO 获取人员相关信息
//            if(empFromAliwork!=null){
            createEmpAbnormalList(aliWorkDTO, abnormalType, null);
//            }

        }
    }


    /**
     * 判断是否有打卡结果
     * 不在考勤组的有些打卡结果为空
     *
     * @param aliWorkDTO
     * @return 返回false 表示打卡结果为空
     */
    private Boolean isComment(AliWorkDTO aliWorkDTO) {
        Boolean isComment = true;
        String comment1 = aliWorkDTO.getPunchComment1();
        String comment2 = aliWorkDTO.getPunchComment2();
        if (StringUtils.isEmpty(comment1) && StringUtils.isEmpty(comment2)) {
            isComment = false;
        }
        return isComment;
    }

    /**
     * 返回上班是否打卡
     *
     * @return
     * true : 上班打卡了
     * false: 上班未打卡
     */
    private Boolean isPunchIn(AliWorkDTO aliWorkDTO) {
        Boolean punchIn = false;
        if (!WorkSheetConstant.ATTENDENCE_MISS_REASON.equals(aliWorkDTO.getPunchComment1())) {
            punchIn = true;
        }
        return punchIn;
    }

    /**
     * 返回上班是否打卡
     *
     * @return true : 下班打卡了
     * false: 下班未打卡
     */
    private Boolean isPunchOut(AliWorkDTO aliWorkDTO) {
        Boolean punchOut = false;
        if (!WorkSheetConstant.ATTENDENCE_MISS_REASON.equals(aliWorkDTO.getPunchComment2())) {
            punchOut = true;
        }
        return punchOut;
    }


    //从map或者是数据库中回去员工详情
    private EmployeesDO getEmpFromAliwork(AliWorkDTO aliWorkDTO) {
        if (StringUtils.isEmpty(aliWorkDTO.getEmployeeName())) {
            LOGGER.error("考勤表中缺失重要字段！考勤详细信息：" + aliWorkDTO);
            return null;
        }

        EmployeesDO attEmp;
        String uniqueId = aliWorkDTO.getEmployeeName() + aliWorkDTO.getAliNumber();
        if (onePersonMap.containsKey(uniqueId)) {      //从map里面去数据
            attEmp = onePersonMap.get(uniqueId);
        } else {                                        //新考勤员工，从数据库中查询数据    //TODO 仍然存在重复的可能,只是可能性比较小了而已
            EmpCondition empCondition = new EmpCondition();
            empCondition.setName(aliWorkDTO.getEmployeeName());
            empCondition.setOutNum(aliWorkDTO.getAliNumber());
            List<EmployeesDO> empForName = employeesMapper.findAllEmp(empCondition);
            if (null == empForName || empForName.size() != 1) {
                LOGGER.error("根据人名查询存在问题！考勤详情：" + aliWorkDTO);    //TODO 如果一开始没有查找到员工，
                return null;
            }
            attEmp = empForName.get(0);     //有且仅有一个参数
            if (null == attEmp.getEmpId() || null == attEmp.getDingId()) {
                LOGGER.error("根据姓名查询人员失败！缺失重要信息！人员详情:" + attEmp);
                return null;
            }

            List<Long> groupIdsByDingId = addressMapper.findGroupIdsByDingId(attEmp.getDingId());
            //一个人可能有多个群
            StringBuilder groupNames = new StringBuilder();
            for (Long groupId : groupIdsByDingId) {
                GroupDO groupById = groupMapper.findGroupById(groupId);
                if (null != groupById || !StringUtils.isEmpty(groupById.getGroupName())) {
                    groupNames.append(groupById.getGroupName());
                }
                //TODO 群组名称的问题
            }
            aliWorkDTO.setGroupName(groupNames.toString());
            attEmp.setGroupIds(groupIdsByDingId);
            aliWorkDTO.setEmpId(attEmp.getEmpId());
            aliWorkDTO.setGroupIds(groupIdsByDingId);
            onePersonMap.put(uniqueId, attEmp);
        }
        return attEmp;
    }

    /**
     * 添加至异常数据List中
     *
     * @param aliWorkDTO  考勤对象
     * @param abnormalNum 错误信息Flag
     */
    private void createEmpAbnormalList(AliWorkDTO aliWorkDTO, int abnormalNum, EmployeesDO employeesDO) throws BaseException {
        if (null == employeesDO) {
            LOGGER.error("数据库中没有此员工,可能原因人员没有同步过来" + aliWorkDTO);
        }
        //1.首先将人员信息查出   先对应的是map(aliNum,abnormalAttendanceDTOList)
        if (aliWorkDTO == null) {
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "考情Excel表中对象为空！");
        }

        AbnormalAttendanceDTO abnormalAttendanceDTO = new AbnormalAttendanceDTO();
        BeanUtils.copyProperties(aliWorkDTO, abnormalAttendanceDTO);
        abnormalAttendanceDTO.setAbnormalityOfAttendance(abnormalNum);
        abnormalAttendanceDTO.setAbnormalityOfAttendanceDescribe(abnormalityOfAttendanceDescribeMap.get(abnormalNum));
        abnormalList.add(abnormalAttendanceDTO);
    }

    /**
     * @param aliWorkDTO 传入考勤对象
     * @return 返回布尔值 如果符合休息条件 返回true，如果不是休息的时候 ，返回false
     * @function 去掉休息，并且将Excel表格中存在的空数据去除
     */
    private boolean removeSpecialAttendance(AliWorkDTO aliWorkDTO) {
        //过滤掉一些不需要计算的考勤
        boolean nomal = true;
        String order = aliWorkDTO.getOrder();//去掉休息
        String punchComment1 = aliWorkDTO.getPunchComment1();//打卡结果1
        String punchComment2 = aliWorkDTO.getPunchComment2();//打卡结果2
        int isEccom = -1;
        int isAAAA = -1;
        if (!StringUtils.isEmpty(order)) {
            isEccom = order.indexOf(WorkSheetConstant.ORDER_ECCOM);
            isAAAA = order.indexOf(WorkSheetConstant.ORDER_AAAA);
            if(order.contains(WorkSheetConstant.ORDER_NO_SCHEDULING)){
                nomal = false;
            }
        }

        if (aliWorkDTO.getEmployeeName() == null || aliWorkDTO.getEmployeeName().equals("")) {     //去除Excel表格中的空数据
            log.error("缺失考勤中重要参数！考勤详情：" + aliWorkDTO);
            nomal =  false;
        }

        if (isEccom != -1 || isAAAA != -1 || WorkSheetConstant.CARD_OUT_ATTENDENCE.equals(punchComment1)
                || WorkSheetConstant.CARD_OUT_ATTENDENCE.equals(punchComment2)) {                               //判断是否是考勤组的问题
            nomal = false;
        }
        if (WorkSheetConstant.CARD_LEAVE.equals(punchComment1) && WorkSheetConstant.CARD_LEAVE.equals(punchComment2)) {     //符合全天上班
            nomal = false;
        }
        if (WorkSheetConstant.CARD_BUSSINESS_TRIP.equals(punchComment1) && WorkSheetConstant.CARD_BUSSINESS_TRIP.equals(punchComment2)) {
            nomal = false;
        }
        if (WorkSheetConstant.CARD_OUT.equals(punchComment1) && WorkSheetConstant.CARD_OUT.equals(punchComment2)) {
            nomal = false;
        }
        //存在月中导出的时候有没有打卡
        if (WorkSheetConstant.CARD_UNPREPARED.equals(punchComment2)) {
            nomal = false;
        }
        return nomal;
    }

    /**
     * 计算复杂工作时间，有调休单（不止一个的那种情况）的那种情况
     * 计算规则：需要工作时间-加班时间
     *
     * @param aliWorkDTO 考勤
     * @return 数据
     */
    private Double countWorkMins(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws ParseException {
        Double totalMins = 0.0;
        Double absentMins = 0.0;        //缺勤分钟数
        if (null != aliWorkDTO.getAttendenceMin()) {
            totalMins = StringUtils2.str2Double(aliWorkDTO.getAttendenceMin());
        }
        totalMins = countWorkMinsWithApproval(aliWorkDTO, totalMins,allAttendenceDOMap);
        if (null != totalMins) {
            if (!StringUtils.isEmpty(aliWorkDTO.getOrder())) {
                if (!aliWorkDTO.getOrder().contains(WorkSheetConstant.ORDER_REST)) {
                    absentMins = DataUtils.doubleFor2(WorkSheetConstant.WORK_HOUR - totalMins);
                }
            }

        }

        //周六、周末的算法
        if (absentMins < 0) {
            absentMins = 0.0;
        }
        if (totalMins < 0) {
            totalMins = 0.0;
        }
        aliWorkDTO.setAttendenceMin(totalMins + "");
        aliWorkDTO.setAbsentMin(absentMins);
        return absentMins;
    }

    /**
     * 计算
     *
     * @param aliWorkDTO
     * @return
     */
    private Double countWeekendMins(AliWorkDTO aliWorkDTO, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws ParseException {
        Double totalMins = 0.0;
        if (null != aliWorkDTO.getAttendenceMin()) {
            totalMins = StringUtils2.str2Double(aliWorkDTO.getAttendenceMin());
        }
        totalMins = countWorkMinsWithApproval(aliWorkDTO, totalMins,allAttendenceDOMap);

        //存在有加班审批单,然后考勤时间为空的情况。
        if (totalMins < 0) {
            totalMins = 0.0;
        }
        return totalMins;
    }

    private Double countWorkMinsWithApproval(AliWorkDTO aliWorkDTO, @NonNull Double totalMins, Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap) throws ParseException {
        String attendenceDate = aliWorkDTO.getDateStr();
        if (StringUtils.isEmpty(aliWorkDTO.getApproval())) {   //无审批单
            return totalMins;
        }
        //有审批单
        String[] approvals = aliWorkDTO.getApproval().split("小时");

        for (String approvalStr : approvals) {         //截取调休单
            String[] strTemp = approvalStr.split(" ");    //最后一个字段为调休单的小时字段
            String leaveStr = strTemp[strTemp.length - 1];
            Long fewDay  = DateUtils.fewDay(approvalStr);
            Double approvalMins = Double.parseDouble(leaveStr);
            Double oneDayMins = reminderApproval(aliWorkDTO,approvalMins,fewDay,allAttendenceDOMap);    //取余后变换成

            if (ExcelUtils.isLeave(approvalStr)) {
                String startDate = getApprovalStartDate(approvalStr);
                String endDate = getApprovalEndDate(approvalStr);
                if(attendenceDate!=null){
                    if(attendenceDate.contains(startDate)||attendenceDate.contains(endDate)){
                        totalMins += oneDayMins;
                    }
                }

            } else if (approvalStr.contains(WorkSheetConstant.APPROVAL_OVERTIME_TYPE)) {
                String dateStr4Day = getApprovalStartDate(approvalStr);
                if (aliWorkDTO.getDateStr().contains(dateStr4Day)) {
                    totalMins -= oneDayMins;
                }
            } else {
                LOGGER.error("考勤表审批单竟然存在另外一种情况！具体考勤信息：" + aliWorkDTO);
            }
        }
        Double correctDoubleMin = DataUtils.doubleFor2(totalMins);
        return correctDoubleMin;
    }

    /**
     * 获取审批单中开始请假的日期
     * @param approvalStr
     * @return
     */
    private String getApprovalStartDate(String approvalStr){
        String dateStr4Day = approvalStr.substring(WorkSheetConstant.SUBSTR_DATESTR_DAY_START_INDEX, WorkSheetConstant.SUBSTR_DATESTR_DAY_END_INDEX);   //截取"03-18"
        if(approvalStr.contains(",")){
            dateStr4Day = approvalStr.substring(WorkSheetConstant.SUBSTR_DATESTR_DAY_START_INDEX+1, WorkSheetConstant.SUBSTR_DATESTR_DAY_END_INDEX);   //多个审批单中间有`,`截取"03-18"
        }
        return dateStr4Day;
    }

    /**
     * 获取审批单中结束日期
     * @param approval
     * @return
     */
    private String getApprovalEndDate(String approval){
        String endDate = "";
        String[] apprlvalTemp = approval.split("小时");
        for(String str : apprlvalTemp){
            if(str!=null){
                if(!str.contains("加班")){
                    endDate = str.split("到")[1].substring(0, 5);
                }
            }
        }
        return endDate;
    }

    /**
     * 功能是为了保证调休单中请假数据有些大于一天的时间，针对这种情况取余，计算一天的时间即可。一天工作时间按8小时计算
     * @param doubleHour 调休单中截取的时间字符串
     *         fewDay  审批单中相差的天数大于天的时候
     * @return resultHour 返回取余后的小时数     111
     */
        private Double reminderApproval(AliWorkDTO aliWorkDTO, Double doubleHour,Long fewDay,Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap){
            Double resultHour = 0.0;
            String aliNum = aliWorkDTO.getAliNumber();
            if(StringUtils.isEmpty(aliNum)){
                log.error("员工阿里工号为空:"+aliWorkDTO);
            }
            String approval = aliWorkDTO.getApproval();
            String attendenceDate = aliWorkDTO.getDateStr();

            if (doubleHour > 8){

                if(!StringUtils.isEmpty(attendenceDate)){
                    String apprlvalStartDate = getApprovalStartDate(approval);
                    String approvalEndDate = getApprovalEndDate(approval);
                    if(!attendenceDate.contains(approvalEndDate)){
                        //请假开始时间不处理
                        resultHour = WorkSheetConstant.WORK_HOUR;
                    }else{
                        //请假结束时间处理
                        resultHour = moreApprovalForDays(aliNum,apprlvalStartDate,approvalEndDate,doubleHour,0.0,allAttendenceDOMap,fewDay);
                    }

                }else{
                    log.error("日期为空:"+aliWorkDTO);
                }


            }else {
                resultHour = doubleHour*60;
            }
            return resultHour;


        }

    /**
     * 判断当前员工考勤 是否为休息日
     * @param aliNum
     * @param startDate
     * @param endDate
     * @param doubleHour 一共请假的小时数
     * @param finalHour  多天请假下 一共上班的小时数
     * @param allAttendenceDOMap
     * @return
     */
    private Double moreApprovalForDays(String aliNum,String startDate,String endDate, Double doubleHour,Double finalHour,Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap,Long fewDay){
        //实际工作时长(请假8小时就相当于上班8小时 不算异常数据)
        Double resultHour = 0.0;
        /**
         * 处理请假多天的情况下需要把有工作时间的累加上去
         * 及多天请假 并第一条请假了又上了半天班
         * 在最后一天算请假时间的时候需要把工作时间累加上去
         */
        AliWorkDTO aliWorkDTO = allAttendenceDOMap.get(aliNum).get(startDate);
        if(aliWorkDTO ==null){
            log.error("根据外包工号和日期找不到员工");
            return resultHour;
        }
        String attendenceDate = aliWorkDTO.getAttendenceMin();
        if(!StringUtils.isEmpty(attendenceDate)){
            finalHour +=Double.parseDouble(attendenceDate);
        }
        if(!StringUtils.isEmpty(aliWorkDTO.getFreeDay())){
            fewDay--;
        }

        if(startDate.equals(endDate)){
            resultHour = doubleHour*60-fewDay*WorkSheetConstant.WORK_HOUR+finalHour;
            return resultHour;
        }else{
            String upDate = dayUp(startDate);
            return moreApprovalForDays(aliNum,upDate,endDate,doubleHour,finalHour,allAttendenceDOMap,fewDay);
        }

    }

    private AliWorkDTO getAliWorkDTO(String aliNum,String date,Map<String,Map<String,AliWorkDTO>> allAttendenceDOMap){
        AliWorkDTO aliWorkDTO = null;
        if(!StringUtils.isEmpty(aliNum)){
            if(!StringUtils.isEmpty(date)){
                aliWorkDTO = allAttendenceDOMap.get(aliNum).get(date);
            }
        }
        return aliWorkDTO;
    }

    /**
     * "07-12"  -> "07-13"
     * @param date
     * @return
     */
    private String dayUp(String date){
        String result = "";
        if(!StringUtils.isEmpty(date)){
         String[] dateTemp = date.split("-");
         result = dateTemp[0]+"-"+(Integer.parseInt(dateTemp[1])+1);
        }
        return result;
    }

    private boolean serious_late(AliWorkDTO aliWorkDTO) throws ParseException, CommonException {
        if(StringUtils.isEmpty(aliWorkDTO.getPunchTime1())||StringUtils.isEmpty(aliWorkDTO.getDateStr())){
          return false;
        }
        boolean result = false;
        Date workTime = DateUtils.formatPunchTimeToDate(aliWorkDTO.getPunchTime1(),aliWorkDTO.getDateStr());
        Date seriousLate = DateUtils.formatPunchTimeToDate(WorkSheetConstant.SERIOUS_LATE,aliWorkDTO.getDateStr());
       if(DateUtils.dateCompare(workTime,seriousLate) || aliWorkDTO.getPunchComment1().contains(WorkSheetConstant.CARD_RESULT_SERIOUS_LATE)){
           result = true;
       }
        return result;
    }

    public static void main(String[] args) {
        double a = 123;
        double b = 223;
        System.out.println(a + b);
        System.out.println(a * 60);
        System.out.println(b - a);
    }

}